*** shade.c	Mon Oct 11 14:59:56 1993
--- shade.c.frac	Mon Oct 11 14:46:03 1993
***************
*** 27,32 ****
--- 27,33 ----
  #include "libsurf/atmosphere.h"
  #include "options.h"
  #include "stats.h"
+ #include "viewing.h"
  
  Medium	TopMedium;
  Atmosphere *AtmosEffects;
***************
*** 119,125 ****
  	 */
  	for (lp = Lights; lp; lp = lp->next)
  		LightRay(lp, pos, nrm, gnrm, smooth, &refl, surf,
! 				ray->depth, ray->sample, ray->time, color);
  
  	if (ray->depth >= Options.maxdepth)
  		/*
--- 120,126 ----
  	 */
  	for (lp = Lights; lp; lp = lp->next)
  		LightRay(lp, pos, nrm, gnrm, smooth, &refl, surf,
! 				ray, color);
  
  	if (ray->depth >= Options.maxdepth)
  		/*
***************
*** 162,185 ****
   * Lighting calculations
   */
  static void
! LightRay(lp, pos, norm, gnorm, smooth, reflect, surf, depth, samp, time, color)
  Light *lp;			/* Light source */
  Vector *pos, *norm, *gnorm;	/* hit pos, shade norm, geo norm */
  int smooth;			/* true if shade and geo norm differ */
  Vector *reflect;		/* reflection direction */
  Surface *surf;			/* surface characteristics */
! int depth, samp;		/* ray depth, sample # */
! Float time;
  Color *color;			/* resulting color */
  {
  	Color lcolor;
  	Ray newray;
! 	Float costheta, cosalpha, dist;
  
  	newray.pos = *pos;
! 	newray.depth = depth;
! 	newray.sample = samp;
! 	newray.time = time; 
  	newray.media = (Medium *)NULL;	
  
  	LightDirection(lp, pos, &newray.dir, &dist);
--- 163,186 ----
   * Lighting calculations
   */
  static void
! LightRay(lp, pos, norm, gnorm, smooth, reflect, surf, ray, color)
  Light *lp;			/* Light source */
  Vector *pos, *norm, *gnorm;	/* hit pos, shade norm, geo norm */
  int smooth;			/* true if shade and geo norm differ */
  Vector *reflect;		/* reflection direction */
  Surface *surf;			/* surface characteristics */
! Ray *ray;
  Color *color;			/* resulting color */
  {
  	Color lcolor;
  	Ray newray;
! 	Float costheta, cosalpha, cosphi, dist;
  
+         newray.type = SHADOW_RAY;
  	newray.pos = *pos;
! 	newray.depth = ray->depth;
! 	newray.sample = ray->sample;
! 	newray.time = ray->time; 
  	newray.media = (Medium *)NULL;	
  
  	LightDirection(lp, pos, &newray.dir, &dist);
***************
*** 186,191 ****
--- 187,202 ----
  
  	costheta = dotp(&newray.dir, norm);
  
+ /* ray viewpoint is the position at the light source */
+         VecAddScaled(newray.pos, dist, newray.dir, &newray.viewpoint);
+ /* shadow ray "sees" same area at intersection position as parent ray */
+         cosphi = -dotp(&ray->dir, norm);
+         if (cosphi < EPSILON) cosphi = EPSILON;
+         newray.width = PixelSize(ray, VecDist(&newray.pos, &ray->pos)) / cosphi * costheta;
+ /* shadow rays become smaller as they approach the light source */
+         newray.viewdist = -dist;   
+         newray.stretch = 1.;
+ 
  	if (smooth) {
  		cosalpha = dotp(&newray.dir, gnorm); 
  		/*
***************
*** 278,287 ****
  {
  	int total_int_refl = FALSE;
  	Ray NewRay;
! 	Float dist;
  	Color newcol;
  	HitList hittmp;		/* Geom intersection record */
  
  	NewRay.pos = *pos;		/* Origin == hit point */
  	NewRay.media = ray->media;	/* Media == old media */
  	NewRay.sample = ray->sample;
--- 289,299 ----
  {
  	int total_int_refl = FALSE;
  	Ray NewRay;
! 	Float dist, cosi, cosr;
  	Color newcol;
  	HitList hittmp;		/* Geom intersection record */
  
+         NewRay.type = REFRACT_RAY;
  	NewRay.pos = *pos;		/* Origin == hit point */
  	NewRay.media = ray->media;	/* Media == old media */
  	NewRay.sample = ray->sample;
***************
*** 322,327 ****
--- 334,360 ----
  	 */
  
  	if (!total_int_refl) {
+ /* good for planar refraction only */
+ /* cosi = cos angle(incident ray, surface normal)
+  * cosr = cos angle(refracted ray, surface normal) */
+                 cosi = -dotp(&ray->dir, norm);                
+ 		if (cosi < EPSILON) cosi = EPSILON;
+                 cosr = -dotp(&NewRay.dir, norm);                
+ /*
+  *                       nr   cosr  2
+  * NewRay.viewdist = y = -- ( ---- )  * x 
+  *                       ni   cosi
+  * where x = distance newray origin to oldray viewpoint.
+  */
+                 NewRay.viewdist = (NewRay.media ? NewRay.media->index : TopMedium.index) / (ray->media ? ray->media->index : TopMedium.index) * 
+                                 (cosr * cosr) / (cosi * cosi) * 
+                                 (ray->viewdist < 0. ? -1. : 1.) * VecDist(&ray->viewpoint, &NewRay.pos);
+ /* NewRay.viewpoint = NewRay.pos - y * NewRay.dir */
+                 VecAddScaled(NewRay.pos, -NewRay.viewdist, NewRay.dir, &NewRay.viewpoint);
+ /* both rays "see" same area at intersection point */
+                 NewRay.width = PixelSize(ray, VecDist(&ray->pos, &NewRay.pos)) * cosr / cosi;
+                 NewRay.stretch = 1.;
+ 
  		Stats.RefractRays++;
  		hittmp.nodes = 0;
  		dist = FAR_AWAY;
***************
*** 360,365 ****
--- 393,399 ----
  	Color newcol;
  	Float dist;
  
+         NewRay.type = REFLECT_RAY;
  	NewRay.pos = *pos;		/* Origin == hit point */
  	NewRay.dir = *dir;		/* Direction == reflection */
  	NewRay.media = ray->media;	/* Medium == old medium */
***************
*** 366,371 ****
--- 400,413 ----
  	NewRay.sample = ray->sample;
  	NewRay.time = ray->time;
  	NewRay.depth = ray->depth + 1;
+ 
+ /* good for planar reflections only */
+ /* new viewpoint is mirrored old one. width at intersection point is the same */
+         NewRay.viewdist = (ray->viewdist < 0. ? -1. : 1.) * VecDist(&ray->viewpoint, &NewRay.pos);
+         NewRay.width = PixelSize(ray, VecDist(&ray->pos, &NewRay.pos));
+         VecAddScaled(NewRay.pos, -NewRay.viewdist, NewRay.dir, &NewRay.viewpoint);
+         NewRay.stretch = 1.;
+ 
  	Stats.ReflectRays++;
  	hittmp.nodes = 0;
  	dist = FAR_AWAY;
***************
*** 374,376 ****
--- 416,419 ----
  	ColorMultiply(newcol, *intens, &newcol);
  	ColorAdd(*color, newcol, color);
  }
+ 
